const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const { FFMPEG_PATH } = require("./ffmpeg");
const { videoProcessorBySubtitles } = require("./videoProcessorBySubtitles");
const {
  generateResizeImageCommand,
  generateConcatVideoCommand,
  generateFallbackConcatVideoCommand,
  generateMergeAudioVideoCommand,
  generateMergeSubtitleCommand,
  generateStaticImageVideoCommand,
  generateMergeTwoAudioCommand,
  mergeVideosOrderedCommnand,
  mergeVideosOrderedByListCommand,
} = require("./ffmpegCommands");
const { loadConfig } = require("./config");
const encodeFormat = loadConfig().encodeFormat || "h264_nvenc";
function mergeVideosOrderedByList(listFile, outputPath, transition) {
  try {
    const mergeCommand = mergeVideosOrderedByListCommand(listFile, outputPath, transition);
    console.log("  Merging videos...");
    console.log("  Command:", mergeCommand);
    execSync(mergeCommand, { stdio: "inherit" });
    return true;
  } catch (error) {
    console.error("  Error merging videos:", error);
    return false;
  }
}
function mergeVideosOrdered(videoPaths, outputPath) {
  try {
    const mergeCommand = mergeVideosOrderedCommnand(videoPaths, outputPath);
    console.log("  Merging videos...");
    console.log("  Command:", mergeCommand);
    execSync(mergeCommand, { stdio: "inherit" });
    return true;
  } catch (error) {
    console.error("  Error merging videos:", error);
    return false;
  }
}
/**
 * 清理临时文件
 * @param {string} tempDir - 临时目录路径
 */
function cleanupTempFiles(tempDir) {
  try {
    if (fs.existsSync(tempDir)) {
      const files = fs.readdirSync(tempDir);
      files.forEach(file => {
        fs.unlinkSync(path.join(tempDir, file));
      });
    }
  } catch (error) {
    console.warn("清理临时文件时出错:", error.message);
  }
}

/**
 * 创建媒体序列文件用于视频合成
 * @param {Array} subtitles - 字幕数组
 * @param {Array} validMediaFiles - 有效媒体文件数组
 * @param {string} tempDir - 临时目录路径
 * @param {string|null} firstFrameWithTextPath - 首帧图片路径（如果有）
 * @param {number} videoWidth - 视频宽度
 * @param {number} videoHeight - 视频高度
 * @param {number} totalDuration - 总时长（可选）
 * @returns {string} concat文件路径
 */
function createImageSequence(subtitles, validMediaFiles, tempDir, firstFrameWithTextPath, totalDuration = null) {
  let concatFileContent = "";

  // 从配置文件获取视频尺寸
  let configVideoWidth = 1920;
  let configVideoHeight = 1080;
  try {
    const config = loadConfig();
    configVideoWidth = config.projectSettings.videoWidth || 1920;
    configVideoHeight = config.projectSettings.videoHeight || 1080;
  } catch (error) {
    console.warn("无法加载配置文件，使用默认尺寸:", error.message);
  }

  // 如果存在首帧图片，则首先添加首帧图片（不占用字幕时间）
  let startIndex = 0;
  let firstFrameDuration = 0.5; // 首帧默认显示时间

  if (firstFrameWithTextPath && fs.existsSync(firstFrameWithTextPath)) {
    console.log("  使用处理后的首帧图片:", firstFrameWithTextPath);
    // 将首帧图片转换为视频格式，保持正确的宽高比
    const firstFrameOutputPath = path.join(tempDir, `img_first.mp4`);

    // 使用FFmpeg将图片转换为视频，保持正确的宽高比
    const convertCommand = `"${FFMPEG_PATH}" -y -loglevel quiet -loop 1 -i "${firstFrameWithTextPath}" -vf "scale=w=${configVideoWidth}:h=${configVideoHeight}:force_original_aspect_ratio=decrease,crop=w=min(${configVideoWidth}\\,iw):h=min(${configVideoHeight}\\,ih):x=(iw-min(${configVideoWidth}\\,iw))/2:y=(ih-min(${configVideoHeight}\\,ih))/2,pad=w=${configVideoWidth}:h=${configVideoHeight}:x=(ow-iw)/2:y=(oh-ih)/2:color=black" -c:v ${encodeFormat} -t ${firstFrameDuration} -pix_fmt yuv420p -r 30 "${firstFrameOutputPath}"`;
    execSync(convertCommand);

    if (fs.existsSync(firstFrameOutputPath)) {
      concatFileContent += `file 'img_first.mp4'\n`;
      // 首帧图片显示固定时间（例如0.5秒）
      concatFileContent += `duration ${firstFrameDuration}\n`;
      startIndex = 1; // 标记首帧已处理
    }
  }

  // 为每个字幕条目创建对应的视频片段
  concatFileContent = videoProcessorBySubtitles(subtitles, validMediaFiles, startIndex, totalDuration, tempDir, concatFileContent);

  // 写入concat文件
  const concatFilePath = path.join(tempDir, "input.txt");
  fs.writeFileSync(concatFilePath, concatFileContent, "utf-8");
  return concatFilePath;
}

/**
 * 使用FFmpeg创建带字幕的视频（支持ASS和SRT格式）
 * @param {string} concatFilePath - concat文件路径
 * @param {string} subtitleFile - 字幕文件路径
 * @param {string} tempVideoPath - 临时视频文件路径
 * @returns {boolean} 是否成功
 */
function createVideoWithSubtitles(concatFilePath, subtitleFile, tempVideoPath) {
  try {
    // 首先检查concat文件是否存在且不为空
    if (!fs.existsSync(concatFilePath)) {
      console.error("！！！concat文件不存在:", concatFilePath);
      return false;
    }

    const concatContent = fs.readFileSync(concatFilePath, "utf8");
    if (!concatContent || concatContent.trim() === "") {
      console.error("！！！concat文件为空");
      return false;
    }

    // 检查concat文件中的每个文件是否存在
    const lines = concatContent.trim().split("\n");
    for (let i = 0; i < lines.length; i += 2) {
      if (lines[i].startsWith("file ")) {
        const filename = lines[i].match(/file '(.+?)'/)[1];
        const filepath = path.join(path.dirname(concatFilePath), filename);
        if (!fs.existsSync(filepath)) {
          console.error(`！！！concat文件中引用的文件不存在: ${filepath}`);
          return false;
        }
      }
    }

    // 使用更适合处理统一视频格式的参数
    let videoCommand = generateConcatVideoCommand(concatFilePath, tempVideoPath);
    // console.log('\n  执行视频生成命令:', videoCommand);
    console.log("\n  执行视频生成命令...");

    // 将命令写入临时脚本文件执行，避免命令行太长问题
    const tempDir = path.dirname(concatFilePath);
    const scriptPath = path.join(tempDir, "concat_script.bat");
    fs.writeFileSync(scriptPath, videoCommand, "utf-8");
    execSync(`"${scriptPath}"`, { stdio: "ignore" });
    // 执行完后删除临时脚本文件
    if (fs.existsSync(scriptPath)) {
      fs.unlinkSync(scriptPath);
    }

    console.log("  视频生成完成...");
    console.log("  开始处理视频时间轴...");
    // 重置视频时间轴，确保从0开始
    const resetTimeCommand = `"${FFMPEG_PATH}" -y -loglevel error -i "${tempVideoPath}" -vf "setpts=PTS-STARTPTS" -c:v ${encodeFormat} -preset fast -threads 0 -crf 23 -c:a copy "${tempVideoPath}_reset.mp4"`;
    execSync(resetTimeCommand, { stdio: "inherit" });
    fs.renameSync(`${tempVideoPath}_reset.mp4`, tempVideoPath);
    console.log("  视频时间轴处理完成！");

    return true;
  } catch (error) {
    console.error("！！！执行视频生成命令失败:", error.message);
    // 尝试使用不同的参数
    try {
      console.log("  尝试使用不同的参数...");
      let fallbackCommand = generateFallbackConcatVideoCommand(concatFilePath, subtitleFile, tempVideoPath);

      console.log("  执行回退命令:", fallbackCommand);
      execSync(fallbackCommand, { stdio: "inherit" });
      return true;
    } catch (fallbackError) {
      console.error("！！！回退命令也失败了:", fallbackError.message);
      return false;
    }
  }
}

/**
 * 创建静态图片视频（备选方案，支持ASS和SRT格式）
 * @param {string} firstImage - 首帧图片路径
 * @param {string} subtitleFile - 字节文件路径
 * @param {string} tempVideoPath - 临时视频文件路径
 * @param {number} duration - 视频时长
 * @param {number} videoWidth - 视频宽度
 * @param {number} videoHeight - 视频高度
 * @returns {boolean} 是否成功
 */
function createStaticImageVideo(firstImage, subtitleFile, tempVideoPath, duration) {
  try {
    // 调整首帧图片尺寸以适应视频尺寸
    const resizedFirstImagePath = path.join(path.dirname(tempVideoPath), "resized_first_image.jpg");
    try {
      const resizeCommand = generateResizeImageCommand(firstImage, resizedFirstImagePath);
      execSync(resizeCommand);
      firstImage = resizedFirstImagePath;
    } catch (resizeError) {
      console.warn("调整首帧图片尺寸失败，使用原始图片", resizeError.message);
    }

    let videoCommand = generateStaticImageVideoCommand(firstImage, subtitleFile, tempVideoPath, duration);

    console.log("执行备选视频生成命令:", videoCommand);
    execSync(videoCommand, { stdio: "inherit" });
    return true;
  } catch (error) {
    console.error("！！！创建静态图片视频失败:", error.message);
    return false;
  }
}

/**
 * 合并音频和视频
 * @param {string} tempVideoPath - 临时视频文件路径
 * @param {string} audioFile - 音频文件路径
 * @param {string} outputFile - 输出文件路径
 * @param {number} targetDuration - 目标时长（秒），可选参数
 * @returns {boolean} 是否成功
 */
function mergeAudioVideo(tempVideoPath, audioFile, outputFile, targetDuration = null) {
  try {
    const mergeCommand = generateMergeAudioVideoCommand(tempVideoPath, audioFile, outputFile, targetDuration);
    console.log("  执行音视频合并命令:", mergeCommand);
    execSync(mergeCommand, { stdio: "inherit" });
    console.log("  音视频合并成功:", outputFile);
    return true;
  } catch (error) {
    console.error("！！！合并音视频失败:", error.message);
    return false;
  }
}

/**
 * 合并两个音频文件
 * @param {string} startAudioFile - 开头音频文件路径
 * @param {string} mainAudioFile - 主音频文件路径
 * @param {string} outputFile - 输出文件路径
 * @param {number} targetDuration - 目标时长（秒）
 * @returns {boolean} 是否成功
 */
function mergeTwoAudio(startAudioFile, mainAudioFile, outputFile, targetDuration) {
  try {
    const mergeCommand = generateMergeTwoAudioCommand(startAudioFile, mainAudioFile, outputFile, targetDuration);
    console.log("  执行音频合并命令:", mergeCommand);
    execSync(mergeCommand, { stdio: "inherit" });
    return true;
  } catch (error) {
    console.error("！！！合并音频失败:", error.message);
    return false;
  }
}

/**
 * 合并字幕和视频
 * @param {string} tempVideoPath - 临时视频文件路径
 * @param {string} assFile - 字幕文件路径
 * @param {string} outputFile - 输出文件路径
 * @returns {boolean} 是否成功
 */
function mergeAssVideo(tempVideoPath, assFile, outputFile) {
  try {
    // 构建FFmpeg命令，将ASS字幕合并到视频中
    const mergeCommand = generateMergeSubtitleCommand(tempVideoPath, assFile, outputFile);

    console.log("\n  执行字幕合并命令:", mergeCommand);
    execSync(mergeCommand, { stdio: "inherit" });
    return true;
  } catch (error) {
    console.error("！！！合并字幕和视频失败:", error.message);
    return false;
  }
}

/**
 * 添加背景图片：
 * 1. 将背景图片转换为与输入video等长的视频(①)
 * 2. 将①与输入视频进行叠加：
 *    - 如果输入视频的宽度不等于背景图片的宽度，
 *    - 则将输入视频的宽度缩放到背景图片的宽度，且保持视频长宽比不变
 *    - 注意不可对输入视频进行切割
 * @param {string} backgroundImage - 背景图片路径
 * @param {string} video - 视频文件路径
 * @param {string} output - 输出文件路径
 */
function addBackgroundImage(backgroundImage, video, output) {
  try {
    // 获取视频时长
    const durationCommand = `"${FFMPEG_PATH}" -i "${video}" 2>&1 | findstr "Duration"`;
    console.log(`  获取视频时长...,command : ${durationCommand}`);
    const durationOutput = execSync(durationCommand, { encoding: "utf-8" });
    console.log("  获取视频时长输出:", durationOutput);
    const durationMatch = durationOutput.match(/Duration: (\d{2}:\d{2}:\d{2}\.\d{2})/);
    let duration;
    if (durationMatch) {
      const timeParts = durationMatch[1].split(":");
      duration = parseFloat(timeParts[0]) * 3600 + parseFloat(timeParts[1]) * 60 + parseFloat(timeParts[2]);
    } else {
      throw new Error("  Could not extract duration from ffmpeg output");
    }
    console.log(`  视频时长: ${duration} 秒`);
    if (!duration) {
      console.error("！！！获取视频时长失败");
      process.exit(1);
    }

    // 获取背景图片尺寸
    const [bgWidth, bgHeight] = [1080, 1920];

    // 创建临时文件名
    const tempDir = path.dirname(output);
    const bgVideoPath = path.join(tempDir, `bg_video.mp4`);

    // 将背景图片转换为视频
    const bgVideoCommand = `"${FFMPEG_PATH}" -y -loglevel quiet -loop 1 -i "${backgroundImage}" -c:v libx264 -t ${duration} -pix_fmt yuv420p "${bgVideoPath}"`;
    execSync(bgVideoCommand);

    // 将输入视频叠加到背景视频上
    // 使用scale2ref过滤器确保输入视频按背景尺寸缩放但保持宽高比
    const targetWidth = Math.round(bgWidth * 0.9); // 宽度缩放为背景的90%
    const overlayCommand = `"${FFMPEG_PATH}" -y -loglevel quiet -i "${bgVideoPath}" -i "${video}" -filter_complex "[1:v]scale=${targetWidth}:-1:force_original_aspect_ratio=decrease[scaled];[0:v][scaled]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1" -c:a copy -c:v libx264 -pix_fmt yuv420p -shortest "${output}"`;
    execSync(overlayCommand);

    // 删除临时背景视频
    if (fs.existsSync(bgVideoPath)) {
      fs.unlinkSync(bgVideoPath);
    }

    console.log("  背景图片添加成功:", output);
    return true;
  } catch (error) {
    console.error("  添加背景图片失败:", error.message);
    return false;
  }
}

module.exports = {
  cleanupTempFiles,
  createImageSequence,
  createVideoWithSubtitles,
  createStaticImageVideo,
  mergeAudioVideo,
  mergeTwoAudio,
  mergeAssVideo,
  mergeVideosOrdered,
  mergeVideosOrderedByList,
  addBackgroundImage,
};
